package edu.princeton.cogsci.wn;

import java.util.*;

/** This abstract class models the functionality required of a WordNet
 *  database implementation.
 */
public abstract class WordNetImpl implements Constants
{
  /** The most recently registered WordNet implementation. */
  private static WordNetImpl currentWNI;


  /* Abstract Methods */


  /** Returns this implementation's name. */
  public abstract String getTitle( );

  /** Returns the word sense key given by its string
   *  representation. This method should be the inverse of
   *  <CODE>WordSenseKey.toString( )</CODE>. It may assume that the string
   *  representation was created from a word sense key from this
   *  implementation.
   *
   *  @see WordSenseKey#toString
   *  @exception WordNetException if the string representation is malformed
   */
  public abstract WordSenseKey lookupWordSenseKey( String key );

  /** Returns the word sense key associated with the parameters, or null
   *  if it doesn't exist.
   */
  public abstract WordSenseKey lookupWordSenseKey(
    String word, int pos, int sense
  );

  /** Returns the synset key given by its string
   *  representation. This method should be the inverse of
   *  <CODE>SynsetKey.toString( )</CODE>. It may assume that the string
   *  representation was created from a synset key from this
   *  implementation.
   *
   *  @see SynsetKey#toString
   *  @exception WordNetException if the string representation is malformed
   */
  public abstract SynsetKey lookupSynsetKey( String key );

  /** Returns the synset key associated with the parameters, or null if it
   *  doesn't exist.
   */
  public abstract SynsetKey lookupSynsetKey(
    String word, int pos, int sense
  );

  /** Returns the word sense specified by the given key. */
  public abstract WordSense lookupWordSense( WordSenseKey key );
 
  /** Returns the synset specified by the given key. */
  public abstract Synset lookupSynset( SynsetKey key );

  /** Returns the synsets specified by all senses of the given word. */
  public abstract Synset[] lookupSynsetAllSenses( String word, int pos );

  public abstract Synset[] lookupSynsetByGloss( String keyword, int pos );

  /** Performs morphological analysis on the given word and returns all
   *  possible base forms in the given part of speech.
   */
  public abstract String[] lookupBaseForms( String word );


  /* ***** Implemented Methods ****** */

  public static WordNetImpl getCurrentWNI( )
  {
    return currentWNI;
  }

  public static void setCurrentWNI( WordNetImpl wni )
  {
    currentWNI = wni;
  }

  public int toRelation( String relation )
  {
    for ( int i = 0; i < relationSymbols.length; i++ )
      if ( relationSymbols[i].equals( relation ) )
        return i;
    return -1;
  }

  /** This method returns the canonical form of a word in WordNet, the form
   *  that is stored in the index files. It performs the following
   *  (non-morphological) analysis:<BR>
   *  <UL>
   *    <LI>Strips adjective markers from the end
   *    <LI>Replaces spaces with underscores
   *    <LI>Converts to lowercase
   *  </UL>
   */
  public static String toCanonicalForm( String form )
  {
    if ( form == null )
      throw new IllegalArgumentException( "form can't be null." );
    if ( form.indexOf( '(' ) != -1 )
      form = form.substring( 0, form.indexOf( '(' ) );
    return form.toLowerCase( ).replace( ' ', '_' );
  }

  /** Returns the synsets specified by the given word and part of speech, in 
   *  all base forms and senses. This method first checks the given form of the
   *  word, and then calls lookupBaseForms( ) to get other possible forms.
   *  For each form, it calls lookupSynsetAllSenses( ). Returns a hashtable
   *  whose keys are Strings representing word forms and whose values are
   *  arrays of Synsets.
   */
  public Hashtable lookupSynsetAllForms( String word, int pos )
  {
    if ( pos != Constants.ANY_POS )
    {
      String posStr = posStrings[ pos ] + ": ";
      String[] baseForms = lookupBaseForms( word );
      Hashtable synsets = new Hashtable( );
      Synset[] nullFormSynsets = lookupSynsetAllSenses( word, pos );
      if ( nullFormSynsets.length > 0 )
        synsets.put( posStr + word, nullFormSynsets );
      for ( int i = 0; i < baseForms.length; i++ )
      {
        Synset[] sss = lookupSynsetAllSenses( baseForms[i], pos );
	if ( sss.length > 0 )
          synsets.put( posStr + baseForms[i], sss );
      }
      return synsets;
    }
    else
    {
      Hashtable table = new Hashtable( );
      table.putAll( lookupSynsetAllForms( word, Constants.NOUN ) );
      table.putAll( lookupSynsetAllForms( word, Constants.VERB ) );
      table.putAll( lookupSynsetAllForms( word, Constants.ADJECTIVE ) );
      table.putAll( lookupSynsetAllForms( word, Constants.ADVERB ) );
      table.putAll( lookupSynsetAllForms( word, Constants.SATELLITE ) );
      return table;
    }
  }

  public void updateSynset( SynsetKey sk, Synset ss, String user, String pass )
    throws WordNetEditException
  {
    throw new UnsupportedOperationException( "WordNetImpl.updateSynset" );
  }

  public void addSynset( Synset ss, String user, String pass )
    throws WordNetEditException
  {
    throw new UnsupportedOperationException( "WordNetImpl.addSynset" );
  }

  public void removeSynset( SynsetKey sk, String reason, String user, String pass )
    throws WordNetEditException
  {
    throw new UnsupportedOperationException( "WordNetImpl.removeSynset" );
  }

  public void reassignSynset( SynsetKey sk, int oldOwner, String user, String pass )
    throws WordNetEditException
  {
    throw new UnsupportedOperationException( "WordNetImpl.reassignSynset" );
  }
}





